/*
 * Copyright 2010 GP Software
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * DefaultDataHandler.java | Created on April 24, 2010
 */
package org.gp.gpetl.handler;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang.StringUtils;
import org.gp.gpetl.config.BeanMapping;
import org.gp.gpetl.config.ConfigObject;
import org.gp.gpetl.dao.Dao;
import org.gp.gpetl.exception.DaoException;
import org.gp.gpetl.exception.DataHandlingException;
import org.gp.gpetl.exception.DataLoadingException;
import org.gp.gpetl.exception.MappingException;
import org.gp.gpetl.loader.DataLoader;
import org.gp.gpetl.mapper.ConfigMapper;

import java.io.File;
import java.net.URL;
import java.util.Collection;
import java.util.List;

/**
 * Default implementation for a data handler
 *
 * @author Paul Augustine C. Mendoza
 * @since 1.0
 */
public class DefaultDataHandler implements DataHandler {

    /**
     * The mapping service
     */
    private ConfigMapper mappingService;

    /**
     * The loading service
     */
    private DataLoader loadingService;

    /**
     * The dao
     */
    private Dao dao;

    /**
     * The csv file input path
     */
    private String basePath;

    /**
     * Sets the dao
     *
     * @param dao the dao to set
     */
    public void setDao(Dao dao) {
        this.dao = dao;
    }

    /**
     * Sets the file input path
     *
     * @param basePath the file input path to set
     */
    public void setBasePath(String basePath) {
        this.basePath = basePath;
    }

    /**
     * Sets the mapping service
     *
     * @param mappingService the mapping service to set
     */
    public void setMappingService(ConfigMapper mappingService) {
        this.mappingService = mappingService;
    }

    /**
     * Sets the loading service
     *
     * @param loadingService the loading service to set
     */
    public void setLoadingService(DataLoader loadingService) {
        this.loadingService = loadingService;
    }

    /**
     * @see org.gp.gpetl.handler.DataHandler#handle()
     */
    public void handle() throws DataHandlingException {
        StringBuffer msg = new StringBuffer();
        if (!hasValidParameters(msg)) {
            throw new DataHandlingException(
                    "Invalid configuration parameters: " + msg, this);
        }
        File root = new File(this.basePath);
        Collection<File> files =
                FileUtils.listFiles(root, new String[]{"csv"}, false);
        ConfigObject config;
        List<String[]> data;
        int totalCount = 0;
        int batchCount = 0;
        for (File file : files) {
            try {
                batchCount = 0;
                System.out.println("Processing " + file.getName());
                config = this.mappingService.getConfig(
                        FilenameUtils.getBaseName(file.getPath()));
                data = this.loadingService.load(file);
                batchCount = this.dao.insert((BeanMapping) config, data);
                totalCount += batchCount;
                System.out.println("Processed " + batchCount + " records.");
            } catch (MappingException e) {
                throw new DataHandlingException(e, this);
            } catch (DataLoadingException e) {
                throw new DataHandlingException(e, this);
            } catch (DaoException e) {
                throw new DataHandlingException(e, this);
            }
        }
        System.out.println("Total records processed : " + totalCount);
    }

    /**
     * Checks if the parameters are valid
     *
     * @param msg error message
     * @return true if valid
     */
    private boolean hasValidParameters(StringBuffer msg) {
        if (this.basePath == null) {
            msg.append("Input directory should not be null.");
            return false;
        }
        File root = new File(this.basePath);
        if (!root.isDirectory()) {
            msg.append(this.basePath + " is not a directory.");
            return false;
        }
        if (StringUtils.isBlank(this.basePath)) {
            // If this is blank, assume current path
            URL url = this.getClass().getClassLoader().getResource(".");
            this.basePath = url.getPath();
        }
        if (!new File(this.basePath).exists()) {
            msg.append("Input directory does not exist.");
            return false;
        }
        return true;
    }

}
